﻿using System;
using System.Collections.Generic;
using Guitar.Comet.Customer;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;

namespace Guitar.Comet.Client.SignalR
{
    /// <summary>
    /// 配置类
    /// </summary>
    public static class SignalRConfiguration
    {
        private static string _serviceUrl, _serviceName,_clientName;
        private static readonly List<string> _syncSubscribers = new List<string>();
        private static readonly List<string> _asyncSubscribers = new List<string>();
        private static readonly Dictionary<string, ICustomer> _subscriberInstance = new Dictionary<string, ICustomer>();

        public static ISignalRClient Config(this ISignalRClient client, string serviceUrl, string serviceName)
        {
            _serviceName = serviceName;
            _serviceUrl = serviceUrl;
            return client;
        }

        public static ISignalRClient RegisterClient(this ISignalRClient client, string clientName)
        {
            _clientName = clientName;
            return client;
        }

        public static ISignalRClient SyncSubscriber<TFrom, TTo>(this ISignalRClient client, IUnityContainer unityContainer, string subscriberName) where TTo : TFrom
        {
            subscriberName = subscriberName.Trim().ToLower();
            Subscriber<TFrom, TTo>(unityContainer, subscriberName);

            if (_syncSubscribers.Exists(p => p == subscriberName))
                throw new ArgumentException(string.Format("订阅者名称:{0}已存在.", subscriberName));
            _syncSubscribers.Add(subscriberName);
            ResoveSubscriberToInstance(unityContainer, subscriberName);
            return client;
        }

        public static ISignalRClient AsyncSubscriber<TFrom, TTo>(this ISignalRClient client, IUnityContainer unityContainer, string subscriberName) where TTo : TFrom
        {
            subscriberName = subscriberName.Trim().ToLower();
            Subscriber<TFrom, TTo>(unityContainer, subscriberName);

            if (_asyncSubscribers.Exists(p => p == subscriberName))
                throw new ArgumentException(string.Format("异步订阅者名称:{0}已存在.", subscriberName));
            _asyncSubscribers.Add(subscriberName);
            ResoveSubscriberToInstance(unityContainer, subscriberName);
            return client;
        }

        private static void Subscriber<TFrom, TTo>(IUnityContainer unityContainer, string subscriberName) where TTo : TFrom
        {
            if (unityContainer == null) throw new ArgumentNullException("Unity容器为空.");
            unityContainer.RegisterType<TFrom, TTo>(subscriberName, new ContainerControlledLifetimeManager());
        }

        private static void ResoveSubscriberToInstance(IUnityContainer unityContainer, string subscriberName)
        {
            ICustomer customer = unityContainer.Resolve(typeof(ICustomer), subscriberName) as ICustomer;
            _subscriberInstance.Add(subscriberName, customer);
        }

        public static string ServiceUrl
        {
            get
            {
                if (string.IsNullOrEmpty(_serviceUrl))
                    throw new ArgumentNullException("服务地址为空.");
                return _serviceUrl;
            }
        }

        public static string ServiceName
        {
            get
            {
                if (string.IsNullOrEmpty(_serviceName))
                    throw new ArgumentNullException("服务名为空.");
                return _serviceName;
            }
        }

        public static string ClientName
        {
            get
            {
                return _clientName;
            }
        }

        public static List<string> AsyncSubscribers
        {
            get
            {
                return _asyncSubscribers;
            }
        }

        public static List<string> SyncSubscribers
        {
            get
            {
                return _syncSubscribers;
            }
        }

        public static Dictionary<string, ICustomer> SubscriberInstances
        {
            get
            {
                return _subscriberInstance;
            }
        }
    }
}
